package com.googlecode.javatools.classparser.impl;

import java.io.DataInput;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Collection;

import com.googlecode.javatools.classparser.AccessFlagParser;
import com.googlecode.javatools.classparser.AttributeInfoParser;
import com.googlecode.javatools.classparser.ClassFileParser;
import com.googlecode.javatools.classparser.ClassInfoParser;
import com.googlecode.javatools.classparser.ConstantPoolParser;
import com.googlecode.javatools.classparser.FieldInfoParser;
import com.googlecode.javatools.classparser.FileHeaderInfoParser;
import com.googlecode.javatools.classparser.TypesInfoParser;
import com.googlecode.javatools.classparser.types.ClassInfo;
import com.googlecode.javatools.classparser.types.ConstantPool;
import com.googlecode.javatools.classparser.types.FieldInfo;
import com.googlecode.javatools.classparser.types.FileHeaderInfo;
import com.googlecode.javatools.domain.JavaClass;
import com.googlecode.javatools.domain.impl.ParsedJavaClass;

public class ClassFileParserImpl implements ClassFileParser
{
	private final FileHeaderInfoParser fileHeaderInfoParser;
	private final ConstantPoolParser constantPoolParser;
	private final ClassInfoParser classInfoParser;
	private final FieldInfoParser fieldInfoParser;
	private final AttributeInfoParser attributeInfoParser;
	private final AccessFlagParser accessFlagParser;
	private final TypesInfoParser typesInfoParser;

	public ClassFileParserImpl(final FileHeaderInfoParser fileHeaderInfoParser,
			final ConstantPoolParser constantPoolParser, final ClassInfoParser classInfoParser,
			final FieldInfoParser fieldInfoParser, final AttributeInfoParser attributeInfoParser,
			final AccessFlagParser accessFlagParser, final TypesInfoParser typesInfoParser)
	{
		this.fileHeaderInfoParser = fileHeaderInfoParser;
		this.constantPoolParser = constantPoolParser;
		this.classInfoParser = classInfoParser;
		this.fieldInfoParser = fieldInfoParser;
		this.attributeInfoParser = attributeInfoParser;
		this.accessFlagParser = accessFlagParser;
		this.typesInfoParser = typesInfoParser;
	}

	public JavaClass parse(final File classFile) throws Exception
	{
		final DataInput in = createDataInputStream(classFile);

		final FileHeaderInfo fileHeaderInfo = fileHeaderInfoParser.parse(in);

		final ConstantPool constantPool = constantPoolParser.parse(in, fileHeaderInfo);

		final ClassInfo classInfo = classInfoParser.parse(in, constantPool);

		final Collection<FieldInfo> fieldInfos = fieldInfoParser.parse(in, accessFlagParser, attributeInfoParser,
				typesInfoParser, constantPool);

		final Collection<FieldInfo> methodInfos = fieldInfoParser.parse(in, accessFlagParser, attributeInfoParser,
				typesInfoParser, constantPool);

		return new ParsedJavaClass(fileHeaderInfo, classInfo, fieldInfos, methodInfos);
	}

	protected DataInput createDataInputStream(final File classFile) throws FileNotFoundException
	{
		final InputStream inputStream = new FileInputStream(classFile);
		final DataInput in = new DataInputStream(inputStream);
		return in;
	}

}
